/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bgu.ppm.gtm.base.str;

import bgu.ppm.gtm.base.MutableStrategy;
import bgu.sonar.util.collections.Pair;
import java.util.BitSet;
import java.util.Iterator;

/**
 *
 * @author User
 */
public class BitmapStrategy implements MutableStrategy {

    private int numberOfVariables;
    private BitSet domainValues;
    private int domainSize;
    private int numBits;
    private int owningPlayer;

    public BitmapStrategy(int numberOfVariables, int domainSize, int owningPlayer) {
        numBits = (int) Math.ceil((Math.log(domainSize) / Math.log(2)));
        domainValues = new BitSet(numBits * numberOfVariables);
        this.numberOfVariables = numberOfVariables;
        this.domainSize = domainSize;
        this.owningPlayer = owningPlayer;
    }

    @Override
    public void set(int var, int val) {
        if (var >= numberOfVariables || var < 0) {
            throw new IndexOutOfBoundsException("variable " + var + " not in range [0, " + (numberOfVariables - 1) + "]");
        }

        if (val >= domainSize || val < 0) {
            throw new IndexOutOfBoundsException("value " + val + " not in range [0, " + (domainSize - 1) + "]");
        }

        int pos = var * numBits;
        for (int i = 0; i < numBits; i++) {
            domainValues.set(i + pos, (val & 1) == 1);
            val = val >> 1;
        }
    }

    @Override
    public int getNumberOfVariables() {
        return this.numberOfVariables;
    }

    @Override
    public int get(int var) {
        if (var >= numberOfVariables || var < 0) {
            throw new IndexOutOfBoundsException("variable " + var + " not in range [0, " + (numberOfVariables - 1) + "]");
        }

        int pos = var * numBits;
        int res = 0;
        for (int i = 0; i < numBits; i++) {
            res = (res | (domainValues.get(pos + i) ? 1 : 0) << i);
        }

        return res;
    }

    public int getNumberOfBitsPerValue() {
        return numBits;
    }

    @Override
    public Iterator<Pair<Integer, Integer>> iterator() {
        return new Iterator<Pair<Integer, Integer>>() {
            int i = 0;

            @Override
            public boolean hasNext() {
                return i < numberOfVariables;
            }

            @Override
            public Pair<Integer, Integer> next() {
                return new Pair(i, get(i++));
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException("Not supported.");
            }
        };
    }

    @Override
    public int getOwningPlayer() {
        return owningPlayer;
    }
    
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("Strategy{");
        for (int i = 0; i < getNumberOfVariables(); i++) {
            sb.append(get(i)).append(", ");
        }

        if (sb.length() > "Strategy{".length()) {
            sb.delete(sb.length() - ", ".length(), sb.length());
        }

        sb.append("}");

        return sb.toString();
    }

}
